#include "TcpConnection.hpp"
#include "EventLoop.hpp"
#include <sstream>

using std::ostringstream;

namespace ln{

TcpConnection::TcpConnection(int fd,EventLoop * loop)
:_sock(fd)
,_socketIO(fd)
,_localAddr(getLocalAddr())
,_peerAddr(getPeerAddr())
,_loop(loop)
{

}

TcpConnection::~TcpConnection(){
    printf("~TcpConnection()\n");
}

string TcpConnection::receive(){
    //读取一行数据
    char buf[65535] = {0};//开辟64KB空间存储
    int ret = _socketIO.readline(buf,sizeof(buf));
    return string(buf,ret);
}
    
void TcpConnection::send(const string & msg){
    int ret = _socketIO.sendn(msg.data(),msg.size());
    printf("send %d bytes\n",ret);
}

void TcpConnection::sendInLoop(const string & msg){
    if(_loop){
       //将消息的发送函数打包成回调函数交给IO线程中的EventLoop对象
       _loop->runInLoop(std::bind(&TcpConnection::send,this,msg));
    }
}

bool TcpConnection::isClosed() const{
    char buf[10] = {0};
    int ret = _socketIO.recvPeek(buf,sizeof(buf));
    return ret == 0;
}

string TcpConnection::toString() const{
    ostringstream oss;
    oss << "Tcp " << _localAddr.ip() << ":" << _localAddr.port()
        << " --> " << _peerAddr.ip() << ":" << _peerAddr.port();
    return oss.str();
}
    
void TcpConnection::handleNewConnectionCallback(){
    if(_onConnection){
        _onConnection(shared_from_this());
    }
}
    
void TcpConnection::handleMessageCallback(){
    if(_onMessage){
        _onMessage(shared_from_this());
    }
}

void TcpConnection::handleCloseCallback(){
    if(_onClose){
        _onClose(shared_from_this());
    }
}

InetAddress TcpConnection::getLocalAddr(){
    struct sockaddr_in addr;
    memset(&addr,0,sizeof(addr));
    socklen_t len = sizeof(addr);

    int ret = getsockname(_sock.fd(),(struct sockaddr *)&addr,&len);
    if(ret < 0){
        perror("getsockname");
    }

    return InetAddress(addr);
}
    
InetAddress TcpConnection::getPeerAddr(){
    struct sockaddr_in addr;
    memset(&addr,0,sizeof(addr));
    socklen_t len = sizeof(addr);

    int ret = getpeername(_sock.fd(),(struct sockaddr *)&addr,&len);
    if(ret < 0){
        perror("getpeername");
    }

    return InetAddress(addr);
}

}//end of namespace ln
